

#include <hidef.h>           /* common defines and macros */
#include <mc9s12dp512.h>     /* derivative information */
#include "PLL.h"
#include "Timer.h"
#include "SCI_GPS.h"
#include "Scheduler.h"


#pragma LINK_INFO DERIVATIVE "mc9s12dp512"


#define SCI_GPS 1    //serial port gps is on (we have to change driver if this isn't 1)

unsigned long globalClk=0; //sample time sent to fonera

//AUXILLARY FUNCTIONS

//returns 1 if str1 == str2
//You're gonna drive every c programmer on earth insane with this
//the string.h strCmp 
unsigned char strCmp(char *str1, char *str2){
  unsigned char idx=0;
  unsigned char same=1;
  unsigned char done=0;

  while(same && !done){
    if(str1[idx] != str2[idx]) { same = 0; }
    if(str1[idx] == 0 || str2[idx] == 0) { done = 1; }
    idx += 1;
  }
  return same;
}

//DEVICE FOREGROUND FUNCTIONS

//GPS stuff
extern char GPSDataBuf[MAX_GPSSTR_LEN]; //buffer for gps data
extern unsigned char updateGPSData;
char GPSData[GPS_NUM_TYPES][MAX_GPSSTR_LEN]; //most recent data
char GpsTag[GPS_TAG_LEN+1];
unsigned char GpsIdx=0;
unsigned char GpsType=0; //represents the type of gps data string we're currently processing

//updates gps data from buffer
void parseGpsData(void){
  unsigned char i;
  while(updateGPSData) { //updateGPSData set by ISR and waits for it to be 0 before refilling buffer
    
    //GpsIdx will tell use what phase of data capture we're in
    if(GpsIdx >= MAX_GPSSTR_LEN) {  //error
      updateGPSData = 0;
      GpsIdx = 0;
    }
    else if(GpsIdx == 0){ //initial state
      if(GPSDataBuf[GpsIdx] == '$'){ //start token
        GpsTag[GpsIdx] = GPSDataBuf[GpsIdx];
        GpsIdx += 1;
      } 
      else{
        updateGPSData = 0; 
      }
    }    
    else if(GpsIdx > 0 && GpsIdx < GPS_TAG_LEN){ //construct GPS tag
      GpsTag[GpsIdx] = GPSDataBuf[GpsIdx];
      GpsIdx += 1;
    }
    else if(GpsIdx == GPS_TAG_LEN){ //by this time we have the full GPS tag and can begin filling the correct buffer
      GpsTag[GpsIdx] = 0; //complete the string
      if( strCmp(GpsTag, TAG_GPGGA) ) {
        GpsType = TYPE_GPGGA; 
      }
      else if( strCmp(GpsTag, TAG_GPRMC) ) { 
        GpsType = TYPE_GPRMC;
      }
      else if( strCmp(GpsTag, TAG_GPGSA) ) {
        GpsType = TYPE_GPGSA;
      } 
      else { //not a tag we care about
        GpsIdx = 0; 
        updateGPSData = 0;   
      }
    
      if(GpsIdx != 0) { //if we found a tag we want
        GpsIdx += 1;
      } 
    }
    else if(GPSDataBuf[GpsIdx] != LF){
      GpsIdx += 1;
    }
    else{ //done with string
      for(i=0; i<=GpsIdx; i++){ //copy buffer into data var
        GPSData[GpsType][i] = GPSDataBuf[i];
      }
      GPSData[GpsType][GpsIdx+1] = 0;
      GpsIdx = 0;
      updateGPSData = 0;
    }
  }
}

//BACKGROUND FUNCTIONS

//keep track of long period time
void incGClk(void){
  globalClk += 65536L;     
}

//periodic background functions to set flags for foreground SCI transfer
unsigned char sendGrpA=0, sendGrpB=0; //flags for FG/BG communication

void logGrpA(void){
  sendGrpA = 1;  
}

void logGrpB(void){
  sendGrpB = 1;  
}

void main(void) {
  unsigned char GPSRMC_EN=1, GPSGSA_EN=1, GPSGGA_EN=1; //what gps data we're sending

  //PLL_Init();   // Eclk @ 24MHz
  //Timer_Init(); // TCNT @ 333.3ns, TOF @ 21.84478ms 
  //SCI_Init(SCI_FONERA,38400);
  SCI_Init(SCI_GPS,4800);
  Scheduler_Init(); //this assumes TCNT @ 333.3ns
  
  //schedule periodic logging
  //(void)Scheduler_AddEvent(&incGClk,1,0);      //32-bit clk inc
  (void)Scheduler_AddEvent(&logGrpA,45,51180); //1 hz (45 TOFs, 51180 TCNTs)
  (void)Scheduler_AddEvent(&logGrpB,4,37863);  //10 hz (4 TOFs, 37863 TCNTs)
  
  //foreground tasks
  for(;;){
    if(updateGPSData){ //GPS specific foreground update task
      parseGpsData();  
    }
    
    if(sendGrpA){ //its time to log GrpA
      SCI_OutChar(SCI_FONERA, START_TRANS);
      SCI_OutUDec32(SCI_FONERA, globalClk+TCNT); //sample timestamp
      SCI_OutUDec(SCI_FONERA, 0); //data group identifier
      
      //send sample data
      //gps data 
      if(GPSRMC_EN) SCI_OutString(SCI_FONERA,GPSData[TYPE_GPRMC]);
      if(GPSGSA_EN) SCI_OutString(SCI_FONERA,GPSData[TYPE_GPGSA]); 
      if(GPSGGA_EN) SCI_OutString(SCI_FONERA,GPSData[TYPE_GPGGA]); 
      
      //other group a (1hz) data transfers

      
      SCI_OutChar(SCI_FONERA, END_TRANS);
      sendGrpA = 0; //ack data send request
    }
    
    if(sendGrpB){ //its time to log GrpB
      SCI_OutChar(SCI_FONERA, START_TRANS);
      SCI_OutUDec32(SCI_FONERA, globalClk+TCNT); //sample timestamp
      SCI_OutUDec(SCI_FONERA, 1); //data group identifier
      
      //send sample data 
      
      //other group b (10hz) data transfers

      
      SCI_OutChar(SCI_FONERA, END_TRANS);
      sendGrpB = 0; //ack data send request
    }
  }
}








